﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
using DCT.Model;

namespace DCT.ViewModel
{
    public class DeviceMapViewModel : WorkspaceViewModel
    {
        #region Constructor

        public DeviceMapViewModel(string deviceMapViewName, DeviceMapViewModelRepository deviceMapViewModelRepository)
        {
            if (deviceMapViewName == null)
                throw new ArgumentNullException("DeviceMapLevelName");

            DisplayName = deviceMapViewName;
            IsMainMap = DisplayName == Resource.MainDeviceMapName;
            UndoRedo = new UndoRedo();

            _deviceMapRepository = deviceMapViewModelRepository;
            _deviceViewModelCollection = new ObservableCollection<DeviceBaseViewModel>();
            _deviceRepository = new DeviceViewModelRepository(this);
            _deviceRepository.DeviceAdd += new EventHandler<DeviceViewModelEventArgs>(OnDeviceAddToDeviceRepository);
            _deviceRepository.DeviceRemove += new EventHandler<DeviceViewModelEventArgs>(OnDeviceRemoveFromDeviceRepository);
            _deviceRepository.Init();
        }

        #endregion //Constructor

        #region Fields

        DeviceViewModelRepository _deviceRepository;
        DeviceMapViewModelRepository _deviceMapRepository;
        ObservableCollection<DeviceBaseViewModel> _deviceViewModelCollection;
        EditModeState _editMode;
        PackageCommand _packageCommand;

        #endregion //Fields

        #region Properties

        //public Dispatcher CurrentDispatcher { get; set; }

        public TrackSegmentViewModel TrackSegmentEnd { get; private set; }

        public SwitchViewModel SwitchNormal { get; private set; }

        public SwitchViewModel SwitchReverse { get; private set; }

        public bool IsMainMap { get; private set; }

        public EditModeState EditMode
        {
            get
            {
                if (IsMainMap)
                {
                    return _editMode;
                }

                return EditModeState.Move;
            }
            set
            {
                if (value != _editMode)
                {
                    if (_editMode == EditModeState.DrawTrackSegment)
                    {
                        if (this.DrawTrackSegmentEnd_Can())
                        {
                            this.DrawTrackSegmentEnd_Execute(false);
                        }
                    }

                    if (_editMode == EditModeState.DrawSwitch)
                    {
                        if (this.DrawSwitchNormal_Can())
                        {
                            this.DrawSwitchNormal_Execute(false);
                        }

                        if (this.DrawSwitchReverse_Can())
                        {
                            this.DrawSwitchReverse_Execute(false);
                        }
                    }

                    if (IsMainMap)
                    {
                        _editMode = value;
                    }
                    else
                    {
                        _editMode = EditModeState.Move;
                    }
                    

                    base.OnPropertyChanged("EditMode");
                }
            }
        }

        public UndoRedo UndoRedo { get; private set; }

        public DeviceViewModelRepository DeviceRepository
        {
            get
            {
                return _deviceRepository;
            }
        }

        public DeviceMapViewModelRepository DeviceMapRepository
        {
            get
            {
                return _deviceMapRepository;
            }
        }

        public ObservableCollection<DeviceBaseViewModel> DeviceViewModelCollection
        {
            get
            {            
                return _deviceViewModelCollection;
            }
        }

        public IEnumerable<DeviceBaseViewModel> SelectedDevices
        {
            get
            {
                var selectedDevices = from deviceViewModel in this.DeviceViewModelCollection
                                      where deviceViewModel.IsSelected
                                      select deviceViewModel;

                return selectedDevices;
            }
        }
        
        #endregion //Properties

        #region Events

        public EventHandler CanvasInvalidateMeasureHandler;
        public EventHandler DrawEndHander;

        public delegate void LoactionDelegate(Point pt);
        public LoactionDelegate CanvasLoactionHandler;

        #endregion

        #region Commands

        #region SelectAll

        public bool SelectAll_Can()
        {
            return true;
        }

        public void SelectAll_Execute()
        {
            foreach (var deviceViewModel in this.DeviceViewModelCollection)
            {
                deviceViewModel.IsSelected = true;
            }
        }

        RelayCommand _selectAllCommand;
        public ICommand SelectAllCommand
        {
            get
            {
                if (_selectAllCommand == null)
                    _selectAllCommand = new RelayCommand(param => this.SelectAll_Execute(),
                                                         param => this.SelectAll_Can());

                return _selectAllCommand;
            }
        }

        #endregion

        #region DeselectAll

        public bool DeselectAll_Can()
        {
            return true;
        }

        public void DeselectAll_Execute()
        {
            foreach (DeviceBaseViewModel device in this.SelectedDevices)
            {
                device.IsSelected = false;
            }
        }

        RelayCommand _deselectAllCommand;
        public ICommand DeselectAllCommand
        {
            get
            {
                if (_deselectAllCommand == null)
                    _deselectAllCommand = new RelayCommand(param => this.DeselectAll_Execute(),
                                                           param => this.DeselectAll_Can());

                return _deselectAllCommand;
            }
        }

        #endregion

        #region Copy

        public void Copy_Execute()
        {
            List<DeviceBaseViewModel> cpDeviceViewModels = new List<DeviceBaseViewModel>(this.SelectedDevices);
            foreach(DeviceBaseViewModel deviceViewModel in this.SelectedDevices)
            {
                if (deviceViewModel is TrackSegmentViewModel)
                {
                    if (((TrackSegmentViewModel)deviceViewModel).TSViewModelType == TrackSegmentViewModelType.End)
                    {
                        if (!cpDeviceViewModels.Contains(((TrackSegmentViewModel)deviceViewModel).AnotherTSViewModel))
                        {
                            cpDeviceViewModels.Add(((TrackSegmentViewModel)deviceViewModel).AnotherTSViewModel);
                        }

                        cpDeviceViewModels.Remove(deviceViewModel);
                    }
                }
                else if (deviceViewModel is SwitchViewModel)
                {
                    cpDeviceViewModels.Remove(deviceViewModel);

                    if (!cpDeviceViewModels.Contains(((SwitchViewModel)deviceViewModel).MergeSwViewModel))
                    {
                        cpDeviceViewModels.Add(((SwitchViewModel)deviceViewModel).MergeSwViewModel);
                    }
                }
            }

            Clipboard.Clear();
            Clipboard.SetData(DataFormats.Xaml, Utilities.SerializeDeviceViewModels(DisplayName, cpDeviceViewModels));
        }

        public bool Copy_Can()
        {
            return this.SelectedDevices.Any();
        }

        RelayCommand _copyCommand;
        public ICommand CopyCommand
        {
            get
            {
                if (_copyCommand == null)
                    _copyCommand = new RelayCommand(param => this.Copy_Execute(),
                                                    param => this.Copy_Can());

                return _copyCommand;
            }
        }

        #endregion

        #region Delete

        public void Delete_Execute()
        {
            List<DeviceBaseViewModel> deleteDeviceViewModels = new List<DeviceBaseViewModel>();
            foreach (var deviceViewModel in this.SelectedDevices)
            {
                if (deviceViewModel is TrackSegmentViewModel)
                {
                    deleteDeviceViewModels.Add(deviceViewModel);
                    deleteDeviceViewModels.Add(((TrackSegmentViewModel)deviceViewModel).AnotherTSViewModel);
                }
                else if (deviceViewModel is SwitchViewModel)
                {
                    deleteDeviceViewModels.Add(((SwitchViewModel)deviceViewModel).MergeSwViewModel);
                    deleteDeviceViewModels.Add(((SwitchViewModel)deviceViewModel).NormalSwViewModel);
                    deleteDeviceViewModels.Add(((SwitchViewModel)deviceViewModel).ReverseSwViewModel);
                }
                else
                {
                    deleteDeviceViewModels.Add(deviceViewModel);
                }
            }

            if (deleteDeviceViewModels.Count > 0)
            {
                PackageCommand packageCommand = new PackageCommand();
                this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand);

                foreach (DeviceBaseViewModel deviceViewModel in deleteDeviceViewModels)
                {
                    if (_deviceRepository.Remove(deviceViewModel))
                    {
                        this.UndoRedo.InsertInUnDoRedoForDelete(deviceViewModel);
                    }
                }

                this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand.AnotherPackageCommand);
            }

            
        }

        public bool Delete_Can()
        {
            return this.SelectedDevices.Any();
        }

        RelayCommand _deleteCommand;
        public ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                    _deleteCommand = new RelayCommand(param => this.Delete_Execute(),
                                                      param => this.Delete_Can());

                return _deleteCommand;
            }
        }

        #endregion

        #region Cut

        public void Cut_Execute()
        {
            this.Copy_Execute();
            this.Delete_Execute();
        }

        public bool Cut_Can()
        {
            return this.Copy_Can() && this.Delete_Can();
        }

        RelayCommand _cutCommand;
        public ICommand CutCommand
        {
            get
            {
                if (_cutCommand == null)
                    _cutCommand = new RelayCommand(param => this.Cut_Execute(),
                                                   param => this.Cut_Can());

                return _cutCommand;
            }
        }

        #endregion

        #region Paste

        public void Paste_Execute()
        {
            XElement root = Utilities.LoadSerializedDataFromClipBoard();

            if (root != null)
            {
                List<DeviceBaseViewModel> deviceViewModels = Utilities.DeserializeDeviceViewModels(DisplayName, root, new Point());

                if (deviceViewModels.Count > 0)
                {
                    PackageCommand packageCommand = new PackageCommand();
                    this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand);

                    foreach (DeviceBaseViewModel deviceViewModel in deviceViewModels)
                    {
                        if (this._deviceRepository.Add(deviceViewModel))
                        {
                            this.UndoRedo.InsertInUnDoRedoForInsert(deviceViewModel);
                        }
                    }

                    this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand.AnotherPackageCommand);
                }
            }
        }

        public bool Paste_Can()
        {
            XElement root = Utilities.LoadSerializedDataFromClipBoard();

            if (root != null)
            {
                return (string)root.Attribute(Resource.SerializeDeviceViewModels_Root_Attribute_DeviceMapName) == DisplayName;
            }

            return false;
        }

        RelayCommand _pasteCommand;
        public ICommand PasteCommand
        {
            get
            {
                if (_pasteCommand == null)
                    _pasteCommand = new RelayCommand(param => this.Paste_Execute(),
                                                     param => this.Paste_Can());

                return _pasteCommand;
            }
        }

        #endregion

        #region Undo

        public void Undo_Execute()
        {
            this.UndoRedo.Undo(1);
        }

        public bool Undo_Can()
        {
            return this.UndoRedo.IsUndoPossible();
        }

        RelayCommand _undoCommand;
        public ICommand UndoCommand
        {
            get
            {
                if (_undoCommand == null)
                    _undoCommand = new RelayCommand(param => this.Undo_Execute(),
                                                    param => this.Undo_Can());

                return _undoCommand;
            }
        }

        #endregion

        #region Redo

        public void Redo_Execute()
        {
            this.UndoRedo.Redo(1);
        }

        public bool Redo_Can()
        {
            return this.UndoRedo.IsRedoPossible();
        }

        RelayCommand _redoCommand;
        public ICommand RedoCommand
        {
            get
            {
                if (_redoCommand == null)
                    _redoCommand = new RelayCommand(param => this.Redo_Execute(),
                                                    param => this.Redo_Can());

                return _redoCommand;
            }
        }

        #endregion

        #region Move

        public void Move_Execute(object offset)
        {
            double minLeft = double.MaxValue;
            double minTop = double.MaxValue;

            foreach (DeviceBaseViewModel deviceViewModel in this.SelectedDevices)
            {
                minLeft = Math.Min(deviceViewModel.PositionPoint.X, minLeft);
                minTop = Math.Min(deviceViewModel.PositionPoint.Y, minTop);
            }

            double offsetHorizontal = Math.Max(-minLeft, ((Point)offset).X);
            double offsetVertical = Math.Max(-minTop, ((Point)offset).Y);

            foreach (DeviceBaseViewModel deviceViewModel in this.SelectedDevices)
            {
                deviceViewModel.PositionPoint = new Point(deviceViewModel.PositionPoint.X + offsetHorizontal, deviceViewModel.PositionPoint.Y + offsetVertical);
            }

            this.CanvasInvalidateMeasureHandler(this, new EventArgs());
        }

        public bool Move_Can(object offset)
        {
            return this.SelectedDevices.Any() && (offset is Point);
        }

        RelayCommand _moveCommand;
        public ICommand MoveCommand
        {
            get
            {
                if (_moveCommand == null)
                    _moveCommand = new RelayCommand(this.Move_Execute,
                                                    this.Move_Can);

                return _moveCommand;
            }
        }

        #endregion

        #region Remove

        public bool Remove_Can()
        {
            return !IsMainMap && _deviceMapRepository.Contains(this);
        }

        public void Remove_Execute()
        {
            _deviceMapRepository.Remove(this);
        }

        RelayCommand _removeCommand;
        public ICommand RemoveCommand
        {
            get
            {
                if (_removeCommand == null)
                    _removeCommand = new RelayCommand(param => this.Remove_Execute(),
                                                      param => this.Remove_Can());

                return _removeCommand;
            }
        }

        #endregion

        #region Location

        public bool Location_Can(object pt)
        {
            return pt is Point;
        }

        public void Location_Execute(object pt)
        {
            if (this.CanvasLoactionHandler != null)
            {
                this.CanvasLoactionHandler((Point)pt);
            }
        }

        RelayCommand _locationCommand;
        public ICommand LocationCommand
        {
            get
            {
                if (_locationCommand == null)
                    _locationCommand = new RelayCommand(this.Location_Execute,
                                                        this.Location_Can);

                return _locationCommand;
            }
        }

        #endregion

        #region DrawTrackSegmentBegin

        public bool DrawTrackSegmentBegin_Can(object pt)
        {
            return pt is Point && this.EditMode == EditModeState.DrawTrackSegment && this.TrackSegmentEnd == null;
        }

        public void DrawTrackSegmentBegin_Execute(object pt)
        {
            TrackSegmentModel tsModel = new TrackSegmentModel();
            tsModel.DeviceType = "TrackSegment";

            TrackSegmentGraphModel tsGraphModel = new TrackSegmentGraphModel();
            tsGraphModel.DeviceHeight = 900;
            tsGraphModel.DeviceWidth = 900;
            tsGraphModel.EndPoint = ((Point)pt).ToString();
            tsGraphModel.StartPoint = ((Point)pt).ToString();

            //TrackSegmentViewModel sts = new TrackSegmentViewModel(tsModel, tsGraphModel, TrackSegmentViewModelType.Start);
            //TrackSegmentViewModel ets = new TrackSegmentViewModel(tsModel, tsGraphModel, TrackSegmentViewModelType.End);

            //sts.SetAnotherTrackSegmentViewModel(ets);
            //ets.SetAnotherTrackSegmentViewModel(sts);

            List<DeviceBaseViewModel> tss = DeviceViewModelFactory.GenerateDeviceViewModel(tsModel, tsGraphModel);

            if (this._deviceRepository.Add(tss[0]) && this._deviceRepository.Add(tss[1]))
            {
                PackageCommand packageCommand = new PackageCommand();
                this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand);
                this.UndoRedo.IsInsertEnable = false;
                this._packageCommand = packageCommand.AnotherPackageCommand;
                this.TrackSegmentEnd = tss[1] as TrackSegmentViewModel;
            }
        }

        RelayCommand _drawTrackSegmentBeginCommand;
        public ICommand DrawTrackSegmentBeginCommand
        {
            get
            {
                if (_drawTrackSegmentBeginCommand == null)
                    _drawTrackSegmentBeginCommand = new RelayCommand(this.DrawTrackSegmentBegin_Execute,
                                                                     this.DrawTrackSegmentBegin_Can);

                return _drawTrackSegmentBeginCommand;
            }
        }

        #endregion

        #region DrawTrackSegmentEnd

        public bool DrawTrackSegmentEnd_Can()
        {
            return this.TrackSegmentEnd != null && this._packageCommand != null;
        }

        public void DrawTrackSegmentEnd_Execute(object confirm)
        {
            if ((bool)confirm)
            {
                this.UndoRedo.IsInsertEnable = true;
                this.UndoRedo.InsertInUnDoRedoForInsert(this.TrackSegmentEnd.AnotherTSViewModel);
                this.UndoRedo.InsertInUnDoRedoForInsert(this.TrackSegmentEnd);
                this.UndoRedo.InsertInUnDoRedoForPackage(this._packageCommand);
            }
            else
            {
                this._deviceRepository.Remove(this.TrackSegmentEnd.AnotherTSViewModel);
                this._deviceRepository.Remove(this.TrackSegmentEnd);
                this.UndoRedo.IsInsertEnable = true;
                this.UndoRedo.InsertInUnDoRedoForPackage(this._packageCommand);
                this.UndoRedo.PopUndoStack(1);
            }

            if (DrawEndHander != null)
            {
                DrawEndHander(this, new EventArgs());
            }

            this.TrackSegmentEnd = null;
        }

        RelayCommand _drawTrackSegmentEndCommand;
        public ICommand DrawTrackSegmentEndCommand
        {
            get
            {
                if (_drawTrackSegmentEndCommand == null)
                    _drawTrackSegmentEndCommand = new RelayCommand(this.DrawTrackSegmentEnd_Execute,
                                                                   parm => this.DrawTrackSegmentEnd_Can());

                return _drawTrackSegmentEndCommand;
            }
        }

        #endregion

        #region DrawSwitchMerge

        public bool DrawSwitchMerge_Can(object pt)
        {
            return pt is Point && this.EditMode == EditModeState.DrawSwitch && this.SwitchNormal == null && this.SwitchReverse == null;
        }

        public void DrawSwitchMerge_Execute(object pt)
        {
            SwitchModel swModel = new SwitchModel();
            swModel.DeviceType = "Switch";

            SwitchGraphModel swGraphModel = new SwitchGraphModel();
            swGraphModel.DeviceHeight = 900;
            swGraphModel.DeviceWidth = 900;
            swGraphModel.MergePoint = ((Point)pt).ToString();
            swGraphModel.NormalPoint = ((Point)pt).ToString();
            swGraphModel.ReversePoint = ((Point)pt).ToString();

            List<DeviceBaseViewModel> sws = DeviceViewModelFactory.GenerateDeviceViewModel(swModel, swGraphModel);

            if (this._deviceRepository.Add(sws[0]) && this._deviceRepository.Add(sws[1]) && this._deviceRepository.Add(sws[2]))
            {
                PackageCommand packageCommand = new PackageCommand();
                this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand);
                this.UndoRedo.IsInsertEnable = false;
                this._packageCommand = packageCommand.AnotherPackageCommand;
                this.SwitchNormal = sws[1] as SwitchViewModel;
                //this.SwitchReverse = sws[2] as SwitchViewModel;
            }
        }

        RelayCommand _drawSwitchMergeCommand;
        public ICommand DrawSwitchMergeCommand
        {
            get
            {
                if (_drawSwitchMergeCommand == null)
                    _drawSwitchMergeCommand = new RelayCommand(this.DrawSwitchMerge_Execute,
                                                               this.DrawSwitchMerge_Can);

                return _drawSwitchMergeCommand;
            }
        }

        #endregion

        #region DrawSwitchNormal

        public bool DrawSwitchNormal_Can()
        {
            return this.SwitchNormal != null && this._packageCommand != null;
        }

        public void DrawSwitchNormal_Execute(object confirm)
        {
            if ((bool)confirm)
            {
                this.SwitchReverse = this.SwitchNormal.ReverseSwViewModel;
                //this.UndoRedo.IsInsertEnable = true;
                //this.UndoRedo.InsertInUnDoRedoForInsert(this.TrackSegmentEnd.AnotherTSViewModel);
                //this.UndoRedo.InsertInUnDoRedoForInsert(this.TrackSegmentEnd);
                //this.UndoRedo.InsertInUnDoRedoForPackage(this._packageCommand);
            }
            else
            {
                this._deviceRepository.Remove(this.SwitchNormal.MergeSwViewModel);
                this._deviceRepository.Remove(this.SwitchNormal.NormalSwViewModel);
                this._deviceRepository.Remove(this.SwitchNormal.ReverseSwViewModel);
                this.UndoRedo.IsInsertEnable = true;
                this.UndoRedo.InsertInUnDoRedoForPackage(this._packageCommand);
                this.UndoRedo.PopUndoStack(1);

                if (DrawEndHander != null)
                {
                    DrawEndHander(this, new EventArgs());
                }
            }

            this.SwitchNormal = null;
        }

        RelayCommand _drawSwitchNormalCommand;
        public ICommand DrawSwitchNormalCommand
        {
            get
            {
                if (_drawSwitchNormalCommand == null)
                    _drawSwitchNormalCommand = new RelayCommand(this.DrawSwitchNormal_Execute,
                                                                parm => this.DrawSwitchNormal_Can());

                return _drawSwitchNormalCommand;
            }
        }

        #endregion

        #region DrawSwitchReverse

        public bool DrawSwitchReverse_Can()
        {
            return this.SwitchReverse != null && this._packageCommand != null;
        }

        public void DrawSwitchReverse_Execute(object confirm)
        {
            if ((bool)confirm)
            {
                this.UndoRedo.IsInsertEnable = true;
                this.UndoRedo.InsertInUnDoRedoForInsert(this.SwitchReverse.MergeSwViewModel);
                this.UndoRedo.InsertInUnDoRedoForInsert(this.SwitchReverse.NormalSwViewModel);
                this.UndoRedo.InsertInUnDoRedoForInsert(this.SwitchReverse.ReverseSwViewModel);
                this.UndoRedo.InsertInUnDoRedoForPackage(this._packageCommand);
            }
            else
            {
                this._deviceRepository.Remove(this.SwitchReverse.MergeSwViewModel);
                this._deviceRepository.Remove(this.SwitchReverse.NormalSwViewModel);
                this._deviceRepository.Remove(this.SwitchReverse.ReverseSwViewModel);
                this.UndoRedo.IsInsertEnable = true;
                this.UndoRedo.InsertInUnDoRedoForPackage(this._packageCommand);
                this.UndoRedo.PopUndoStack(1);
            }

            this.SwitchReverse = null;

            if (DrawEndHander != null)
            {
                DrawEndHander(this, new EventArgs());
            }
        }

        RelayCommand _drawSwitchReverseCommand;
        public ICommand DrawSwitchReverseCommand
        {
            get
            {
                if (_drawSwitchReverseCommand == null)
                    _drawSwitchReverseCommand = new RelayCommand(this.DrawSwitchReverse_Execute,
                                                                parm => this.DrawSwitchReverse_Can());

                return _drawSwitchReverseCommand;
            }
        }

        #endregion

        #region Align

        public bool Align_Can()
        {
            return this.SelectedDevices.Any();
        }

        public void Align_Execute(object dir)
        {
            PackageCommand packageCommand = new PackageCommand();
            this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand);

            switch ((string)dir)
            {
                case "Left":
                    double X_min = this.SelectedDevices.Min(v => v.PositionPoint.X - v.DeviceWidth * v.RenderTransformOrigin.X);

                    foreach (var deviceViewModel in this.SelectedDevices)
                    {
                        deviceViewModel.PositionPoint = new Point(X_min + deviceViewModel.DeviceWidth * deviceViewModel.RenderTransformOrigin.X, deviceViewModel.PositionPoint.Y);
                    }
                    break;
                case "Top":
                    double Y_min = this.SelectedDevices.Min(v => v.PositionPoint.Y - v.DeviceHeight * v.RenderTransformOrigin.Y);

                    foreach (var deviceViewModel in this.SelectedDevices)
                    {
                        deviceViewModel.PositionPoint = new Point(deviceViewModel.PositionPoint.X, Y_min + deviceViewModel.DeviceHeight * deviceViewModel.RenderTransformOrigin.Y);
                    }
                    break;
                case "Right":
                    double X_max = this.SelectedDevices.Max(v => v.PositionPoint.X + v.DeviceWidth * (1 - v.RenderTransformOrigin.X));

                    foreach (var deviceViewModel in this.SelectedDevices)
                    {
                        deviceViewModel.PositionPoint = new Point(X_max - deviceViewModel.DeviceWidth * (1 - deviceViewModel.RenderTransformOrigin.X), deviceViewModel.PositionPoint.Y);
                    }
                    break;
                case "Bottom":
                    double Y_max = this.SelectedDevices.Max(v => v.PositionPoint.Y + v.DeviceHeight * (1 - v.RenderTransformOrigin.Y));

                    foreach (var deviceViewModel in this.SelectedDevices)
                    {
                        deviceViewModel.PositionPoint = new Point(deviceViewModel.PositionPoint.X, Y_max - deviceViewModel.DeviceHeight * (1 - deviceViewModel.RenderTransformOrigin.Y));
                    }
                    break;
                default:
                    break;
            }

            this.UndoRedo.InsertInUnDoRedoForPackage(packageCommand.AnotherPackageCommand);
        }

        RelayCommand _alignCommand;
        public ICommand AlignCommand
        {
            get
            {
                if (_alignCommand == null)
                    _alignCommand = new RelayCommand(this.Align_Execute,
                                                      param => this.Align_Can());

                return _alignCommand;
            }
        }

        #endregion

        #endregion

        #region Methods

        void OnDeviceAddToDeviceRepository(object sender, DeviceViewModelEventArgs e)
        {
            if (!this._deviceViewModelCollection.Contains(e.DeviceViewModel))
            {
                this._deviceViewModelCollection.Add(e.DeviceViewModel);
            }
        }

        void OnDeviceRemoveFromDeviceRepository(object sender, DeviceViewModelEventArgs e)
        {
            if (this._deviceViewModelCollection.Contains(e.DeviceViewModel))
            {
                this._deviceViewModelCollection.Remove(e.DeviceViewModel);
            }
        }

        #endregion
    }


    public enum EditModeState
    {
        Insert,
        DrawTrackSegment,
        DrawSwitch,
        Move
    }
}
